package com.eunion.core.common.query;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

public interface QueryContainer<Entity> {

    Predicate toPredicate(Root<Entity> root, CriteriaBuilder cb);

    static class Builder {

        private List<Predicate> list = new ArrayList<>();

        protected Builder() {
            super();
        }

        public static Builder make() {
            return new Builder();
        }

        public <T> Builder apply(Predicate predicate) {
            if (predicate != null) {
                list.add(predicate);
            }
            return this;
        }

        public <T> Builder apply(Query<T> query, Expression<T> expression, CriteriaBuilder cb) {
            Predicate predicate = Optional.ofNullable(query).map(q -> q.toPredicate(expression, cb)).orElse(null);
            if (predicate != null) {
                list.add(predicate);
            }
            return this;
        }

        public Predicate build(CriteriaBuilder cb) {
            if (list.isEmpty()) {
                return null;
            }
            return cb.and(list.stream().toArray(Predicate[]::new));
        }
    }

}
